package vip.xiaonuo.biz.modular.approvalorder.service.impl;

import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.codec.Base64;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.URLUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import vip.xiaonuo.auth.core.pojo.SaBaseLoginUser;
import vip.xiaonuo.auth.core.util.StpLoginUserUtil;
import vip.xiaonuo.biz.core.config.BizPayProperties;
import vip.xiaonuo.biz.modular.approvalorder.entity.BizApprovalOrder;
import vip.xiaonuo.biz.modular.approvalorder.enums.BizApprovalPayTypeEnum;
import vip.xiaonuo.biz.modular.approvalorder.service.AbcPayService;
import vip.xiaonuo.biz.modular.approvalorder.service.BizApprovalOrderService;
import vip.xiaonuo.biz.modular.canteen.entity.BizCanteen;
import vip.xiaonuo.biz.modular.canteen.service.BizCanteenService;
import vip.xiaonuo.common.enums.CommonSwitchEnum;
import vip.xiaonuo.common.exception.CommonException;
import vip.xiaonuo.common.prop.CommonProperties;
import vip.xiaonuo.common.util.EBusPayUtil;
import vip.xiaonuo.common.util.XMLDocument;

import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.Objects;

@Service
@Slf4j
public class AbcPayServiceImpl implements AbcPayService {
    @Resource
    private WxMaService wxMaService;
    @Resource
    private BizApprovalOrderService bizApprovalOrderService;
    @Resource
    private BizCanteenService bizCanteenService;
    @Resource
    private CommonProperties commonProperties;
    @Resource
    private BizPayProperties bizPayProperties;


    public JSONObject createWxOrder(String orderId) {
        BizApprovalOrder approvalOrder = bizApprovalOrderService.queryEntity(orderId);
        if (CommonSwitchEnum.isTrue(approvalOrder.getPayType())) {
            throw new CommonException("该订单已支付");
        }
        if (!Objects.equals(approvalOrder.getApplicantId(), StpUtil.getLoginIdAsString())) {
            throw new CommonException("无权限操作");
        }
        SaBaseLoginUser loginUser = StpLoginUserUtil.getLoginUser();
        BizCanteen canteen = bizCanteenService.getCacheBizCanteen(approvalOrder.getVisitCafeteriaId());
        JSONObject order = new JSONObject();
        //订单号
        order.put("OrderNo", approvalOrder.getOrderSn());
        //交易金额，最多精确小数点后两位
        order.put("OrderAmount", approvalOrder.getCafeteriaPrice());
        //订单描述，必须上送
        order.put("OrderDesc", "到访食堂" + approvalOrder.getVisitCafeteriaName());
        //刷卡支付时，请上送授权码；公众号、小程序、APP支付时，请上送应用的APPID
        order.put("AccountNo", wxMaService.getWxMaConfig().getAppid());
        //公众号、小程序支付时，请上送用户在微信的用户标示openid
        order.put("OpenID", loginUser.getOpenId());
        //微信支付类型，1.JSAPI:公众号支付 2.APP:APP支付 3.MICROPAY:付款码支付
        order.put("PayTypeID", "JSAPI");
        //订单日期
        order.put("OrderDate", DateUtil.format(new Date(), "yyyy/MM/dd"));
        order.put("OrderTime", DateUtil.format(new Date(), DatePattern.NORM_TIME_PATTERN));
        //交易币种，请上送156 人民币
        order.put("CurrencyCode", "156");
        return wxPay(order, commonProperties.getBackendUrl() + "/biz/approvalorder/resultNotify", canteen.getMerchantId(), canteen.getMerchantPrivateKeyUrl(), canteen.getMerchantPrivateKeyPassword());
    }


    public JSONObject wxPay(JSONObject order, String resultNotifyUrl, String merchantID, String merchantPrivateKey, String merchantPrivateKeyPassword) {
        JSONObject request = new JSONObject();
        request.put("Order", order);
        //交易码
        request.put("TrxType", "UnifiedOrderReq");
        //支付账户类型，8：微信支付
        request.put("PaymentType", "8");
        //支付交易渠道，1：internet网络接入 2：手机网络接入 3:数字电视网络接入 4:智能客户端 5：线下渠道
        request.put("PaymentLinkType", "1");
        //支付结果通知方式，0：仅URL页面通知 1：服务器通知和URL页面通知，
        request.put("NotifyType", "1");
        //商户接收支付结果通知地址，商户自己填写
        request.put("ResultNotifyURL", resultNotifyUrl);
        //商品类型，详情参考表格下面类型说明
        //0101:支付账户充值，0201:虚拟类，0202:传统类，0203:实名类，0301:本行转账，0302:他行转账，0401:水费，0402:电费，0403:煤气费，0404:有线电视费，0405:通讯费，0406:物业费，0407:保险费，0408:行政费用，0409:税费，0410:学费，0499:其他，0501:基金，0502:理财产品，0599:其他
        request.put("CommodityType", "0499");
        JSONObject sendData = new JSONObject();
        sendData.put("TrxRequest", request);
        sendData.put("Version", "V3.0.0");
        sendData.put("Format", "JSON");
        JSONObject merchant = new JSONObject();
        merchant.put("ECMerchantType", "EBUS");
        merchant.put("MerchantID", merchantID);
        sendData.put("Merchant", merchant);
        try {
            // 将字符串转换为字节数组，使用UTF-8 编码
            String send = EBusPayUtil.send(merchantPrivateKey, merchantPrivateKeyPassword, sendData.toJSONString());
            return JSONObject.parseObject(send);
        } catch (Exception e) {
            log.info("微信支付异常");
            log.info(e.getMessage());
            throw new CommonException("微信支付异常:{}", e.getMessage());
        }
    }

    public void resultNotify(String paymentResult) {
        log.info("微信支付结果通知");
        log.info(paymentResult);
        String result = paymentResult.replaceFirst("MSG=", "").trim();
        // 第一步：URL 解码
        String urlDecodedStr = URLUtil.decode(result);
        // 第二步：Base64 解码
        byte[] decodeBytes = Base64.decode(urlDecodedStr);
        String xmlContent = new String(decodeBytes, StandardCharsets.UTF_8);
        XMLDocument xmlDocument = new XMLDocument(xmlContent);
        //  验证签名
        boolean success;
        try {
            success = EBusPayUtil.verifyResponse(xmlDocument.getValue("Signature-Algorithm").toString(),
                    xmlDocument.getValue("Signature").toString(),
                    xmlDocument.getValue("Message").toString(),
                    bizPayProperties.getMerchantPrivateKey());
        } catch (Exception e) {
            log.info("微信支付验证签名异常");
            log.info(e.getMessage());
            throw new CommonException(e.getMessage());
        }
        if (!success) {
            log.info("微信支付验证签名未通过");
            throw new CommonException("微信支付验证签名未通过");
        }
        XMLDocument trxResponse = xmlDocument.getValue("Message").getValue("TrxResponse");
        String orderNo = trxResponse.getValue("OrderNo").toString();
        QueryWrapper<BizApprovalOrder> orderQueryWrapper = new QueryWrapper<>();
        orderQueryWrapper.lambda().eq(BizApprovalOrder::getOrderSn, orderNo);
        BizApprovalOrder approvalOrder = bizApprovalOrderService.getOne(orderQueryWrapper);
        if (approvalOrder == null) {
            log.info("订单不存在");
            throw new CommonException("订单不存在");
        }
        if (CommonSwitchEnum.isTrue(approvalOrder.getPayType())) {
            log.info("该订单已支付");
            throw new CommonException("该订单已支付");
        }
        log.info("微信支付成功");
        //修改订单信息
        approvalOrder.setPayType(BizApprovalPayTypeEnum.TRUE.getValue());
        approvalOrder.setPayTime(new Date());
        bizApprovalOrderService.updateById(approvalOrder);
    }
}
